﻿//-----------------------------------------------------------------------
// <copyright file="WizardPagesCollection.cs" company="FastNET Services">
//     Copyright (c) 2008-2009. All Rights Reserved.
// </copyright>
// <license>
//     GPLv2
// </license>
// <warranty>
//     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
//     BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
//     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
//     DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// </warranty>
//-----------------------------------------------------------------------
#region Usings

using System;
using System.Collections;
using GateShift.Common.Controls.Wizards.Pages;

#endregion

namespace GateShift.Common.Controls.Wizards
{
    /// <summary>
    /// Custom collection which we use to work with Wizard Pages. Some
    /// methods of IList interface are overrided to make collection 
    /// type safe. Also Collection support "Changed" event and sorting 
    /// by Index property.
    /// </summary>
    public class WizardPagesCollection : CollectionBase, IComparer
    {
        #region Variables

        private readonly WizardForm _parent;

        #endregion

        #region CTor/DTor

        /// <summary>
        /// Initializes a new instance of the WizardPagesCollection class
        /// </summary>
        /// <param name="parent">WizardForm that is maintaining this collection</param>
        public WizardPagesCollection(WizardForm parent)
        {
            _parent = parent;
        }

        #endregion

        #region Events

        /// <summary>
        /// Event raised when the collection has been modified
        /// </summary>
        public event EventHandler Changed;

        #endregion

        #region IList Properties

        /// <summary>
        /// Gets or sets the WizardPageBase at the indexer
        /// </summary>
        /// <param name="index">Indexer to work with</param>
        /// <returns>WizardPageBase that was found</returns>
        public WizardPageBase this[int index]
        {
            get
            {
                return InnerList[index] as WizardPageBase;
            }

            set
            {
                value.WizardPageParent = _parent;
                value.Index = index;
                InnerList[index] = value;
                RaiseChanged(value);
            }
        }

        #endregion

        #region IList interface implementation

        /// <summary>
        /// Adds a page to the collection
        /// </summary>
        /// <param name="value">WizardPageBase to add to the collection</param>
        /// <returns>Integer of the page added</returns>
        public int Add(WizardPageBase value)
        {
            if (Contains(value))
            {
                return IndexOf(value);
            }

            value.WizardPageParent = _parent;
            int index = InnerList.Add(value);

            if (value.Index < 0)
            {
                value.Index = index;
            }

            RaiseChanged(value);

            return index;
        }

        /// <summary>
        /// Adds a range of pages to the collection
        /// </summary>
        /// <param name="array">Array of WizardPageBase to be added</param>
        public void AddRange(WizardPageBase[] array)
        {
            foreach (WizardPageBase page in array)
            {
                Add(page);
            }
        }

        /// <summary>
        /// Checks to see if the specified WizardPageBase already exists
        /// </summary>
        /// <param name="value">WizardPageBase to check against</param>
        /// <returns>Boolean whether or not the specified item exists already</returns>
        public bool Contains(WizardPageBase value)
        {
            return InnerList.Contains(value);
        }

        /// <summary>
        /// Gets the index of the WizardPageBase
        /// </summary>
        /// <param name="value">WizardPageBase to check against</param>
        /// <returns>The index the item found</returns>
        public int IndexOf(WizardPageBase value)
        {
            return InnerList.IndexOf(value);
        }

        /// <summary>
        /// Inserts the specified WizardPageBase at the index specified
        /// </summary>
        /// <param name="index">Index to insert the WizardPageBase at</param>
        /// <param name="value">WizardPageBase to add to the collection</param>
        public void Insert(int index, WizardPageBase value)
        {
            value.WizardPageParent = _parent;
            InnerList.Insert(index, value);

            if (value.Index < 0)
            {
                value.Index = index;
            }

            RaiseChanged(value);
        }

        /// <summary>
        /// Removes the specified WizardPageBase from the collection
        /// </summary>
        /// <param name="value">WizardPageBase to remove</param>
        public void Remove(WizardPageBase value)
        {
            InnerList.Remove(value);
            RaiseChanged();
        }

        #endregion

        /// <summary>
        /// Sorts the collection of WizardPageBase
        /// </summary>
        public void Sort()
        {
            InnerList.Sort(this);
        }

        /// <summary>
        /// Compares two objects and returns a value indicating whether one is less than, equal to, or greater than the other.
        /// </summary>
        /// <param name="x"> The first object to compare. </param>
        /// <param name="y"> The second object to compare. </param>
        /// <returns>
        /// Value Condition Less than zero <paramref name="x" /> is less than <paramref name="y" />. Zero 
        /// <paramref name="x" /> equals <paramref name="y" />. Greater than zero <paramref name="x" /> 
        /// is greater than <paramref name="y" />.
        /// </returns>
        /// <exception cref="T:System.ArgumentException">
        /// Neither <paramref name="x" /> nor <paramref name="y" /> implements the <see cref="T:System.IComparable" /> interface.
        /// -or- 
        /// <paramref name="x" /> and <paramref name="y" /> are of different types and neither one can handle comparisons with the other. 
        /// </exception>
        public int Compare(object x, object y)
        {
            WizardPageBase page1 = (WizardPageBase)x;
            WizardPageBase page2 = (WizardPageBase)y;

            return (page1.Index > page2.Index) ? 1 : ((page1.Index < page2.Index) ? -1 : 0);
        }

        #region Class Helper methods

        /// <summary>
        /// Raises the Changed event
        /// </summary>
        /// <param name="value">WizardPageBase that was changed</param>
        protected void RaiseChanged(WizardPageBase value)
        {
            if (Changed != null)
            {
                Changed(value, EventArgs.Empty);
            }
        }

        /// <summary>
        /// Raises the Changed Event
        /// </summary>
        protected void RaiseChanged()
        {
            if (Changed != null)
            {
                Changed(this, EventArgs.Empty);
            }
        }

        #endregion

        #region Class overrides

        /// <summary>
        /// Handles the clear completing
        /// </summary>
        protected override void OnClearComplete()
        {
            // raise Changed Event when collection cleared
            RaiseChanged();
        }

        /// <summary>
        /// Handles a new value being set
        /// </summary>
        /// <param name="index">Index of the item</param>
        /// <param name="oldValue">Old value of the item</param>
        /// <param name="newValue">New value of the item</param>
        protected override void OnSetComplete(int index, object oldValue, object newValue)
        {
            WizardPageBase page = (WizardPageBase)newValue;
            page.WizardPageParent = _parent;

            if (page.Index < 0)
            {
                page.Index = index;
            }

            base.OnSetComplete(index, oldValue, page);

            RaiseChanged(page);
        }

        /// <summary>
        /// Handler for a WizardPageBase being added
        /// </summary>
        /// <param name="index">Index of the item added</param>
        /// <param name="value">WizardPageBase being added</param>
        protected override void OnInsertComplete(int index, object value)
        {
            WizardPageBase page = (WizardPageBase)value;
            page.WizardPageParent = _parent;

            if (page.Index < 0)
            {
                page.Index = index;
            }

            base.OnInsertComplete(index, page);

            RaiseChanged(page);
        }

        /// <summary>
        /// Handler for an item being removed
        /// </summary>
        /// <param name="index">Index of the item removed</param>
        /// <param name="value">WizardPageBase being removed</param>
        protected override void OnRemoveComplete(int index, object value)
        {
            RaiseChanged();
        }

        #endregion
    }
}